from django.db import transaction
from django.db.models import Sum
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from financial_info.models import PaymentModel, PaymentItemModel


class PaymentItemSerializer(serializers.ModelSerializer):
    """
        付款单中项目的序列化器
    """

    # 查询当前采购入库单中已经支付的金额
    # read_only=True：只是在序列化的时候用，不是在反序列化的时候用
    # 因为加了read_only=True，不会影响新增和修改
    already_payment = serializers.SerializerMethodField(read_only=True, help_text='已经支付的金额')

    class Meta:
        model = PaymentItemModel
        fields = '__all__'

    def get_already_payment(self, obj):
        """
            查询当前采购入库单中已经支付的金额
            :param obj: PaymentItemModel
            :return: 0或者其他数值
        """
        if obj.purchase_in_storage:
            # purchase_in_storage采购入库单
            pay_dict = PaymentItemModel.objects.filter(purchase_in_storage_id=obj.purchase_in_storage.id).exclude(
                payment__status='0').aggregate(sum=Sum('this_money'))
            if pay_dict:
                # 如果付过款就是pay_dict['sum']，否则就是0
                return pay_dict['sum'] if pay_dict['sum'] else 0
            return 0
        return 0


class PaymentSerializer(serializers.ModelSerializer):
    """
        新增和修改付款单的序列化和反序列化，查询列表的序列化器
    """
    # many=True表示是个列表
    # required=False：这样item_list就不是必填项了，可以省略了，适用于只付定金
    item_list = PaymentItemSerializer(many=True, required=False)

    class Meta:
        model = PaymentModel
        fields = '__all__'

    # 支付定金时，不需要item_list。
    # 同时插入付款单和付款单中的项目，必须重写create
    # validated_data已经验证之后的参数
    def create(self, validated_data):
        if 'item_list' not in validated_data:
            super(PaymentSerializer, self).create(validated_data)
        item_list = validated_data.pop('item_list')
        with transaction.atomic():
            payment = PaymentModel.objects.create(**validated_data)
            for item in item_list:
                PaymentItemModel.objects.create(payment=payment, **item)
        return payment

    def update(self, instance, validated_data):
        # instance：就是正在修改的付款单
        if instance.status != '0':
            # 付款单的状态，0：未审核，1：已审核
            raise ValidationError('付款单已经生效，不能修改')
        # 请求参数中的新项目数据
        # item_list = validated_data.pop('item_list')
        # 如果之前有老数据（之前新增的付款单项目数据）是需要删除掉的
        # old_list = instance.item_list.all()
        with transaction.atomic():
            if 'item_list' in validated_data:
                item_list = validated_data.pop('item_list')
                old_list = instance.item_list.all()

                if old_list.exists():
                    # 然后把旧数据删除，因为在validated_data拿不到老数据的id
                    instance.item_list.all().delete()
                for item in item_list:
                    # 重新插入采购项数据
                    PaymentItemModel.objects.create(payment=instance, **item)

            result = super(PaymentSerializer, self).update(instance=instance, validated_data=validated_data)
        return result

    # 付款单的状态，0：未审核，1：已审核
    # 采购入库单的状态，0：未审核，1：已审核，2：部分付款，3：付款完成（包含欠款）
    # 采购订单的状态/采购单的状态，0：未审核，1：已审核，2：部分入库，3：全部入库，4：已付定金，5：完成采购（货全部入库，付全款完成）
